﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BCCommon;
using BCCommon.Extensions;
using BCCommon.TMS.FreightEnums;
using BCCommon.TMS.Order;
using BCCommon.TMS.Transport;
using BCData.Common.Area;
using BCData.TMS.FreightConfigurationExtention;
using BCData.TMS.VehicleCategoryReference;
using BCData.TMS.VehicleType;
using BCDto.MySql.FreightConfigurationExtention;
using BCDto.Sim.Admin.Admin;
using BCDto.TMS.VehicleType;
using BCEntity.Common.EntityNameConst;
using BCEntity.MySql.FreightConfigurationExtention;
using BCService.TMS.VehicleTypeService;
using BCService.Utils;

namespace BCService.TMS.FreightConfigurationExtention
{
    public class FreightConfigurationExtentionService : IFreightConfigurationExtentionService
    {
        #region 私有变量

        private readonly IFreightConfigurationExtentionData freightConfigurationExtentionData;
        private readonly ICountyData countyData;
        private readonly IRedisService redisService;
        private readonly IVehicleTypeService vehicleTypeService;
        private readonly IVehicleCategoryReferenceData vehicleCategoryReferenceData;
        private readonly IVehicleTypeData vehicleTypeData;
        private readonly string key = string.Format("{0}", EntityNameConst.FreightConfigurationExtentionEntity);
        private readonly string vehicleTypeKey = string.Format("{0}", EntityNameConst.VehicleTypeEntity);

        #endregion 私有变量

        #region 构造函数

        public FreightConfigurationExtentionService(IFreightConfigurationExtentionData freightConfigurationExtentionData,
            ICountyData countyData,
            IRedisService redisService,
            IVehicleTypeService vehicleTypeService,
            IVehicleCategoryReferenceData vehicleCategoryReferenceData,
            IVehicleTypeData vehicleTypeData)
        {
            this.freightConfigurationExtentionData = freightConfigurationExtentionData;
            this.countyData = countyData;
            this.redisService = redisService;
            this.vehicleTypeService = vehicleTypeService;
            this.vehicleCategoryReferenceData = vehicleCategoryReferenceData;
            this.vehicleTypeData = vehicleTypeData;
        }

        #endregion 构造函数

        #region 公共方法

        public FreightConfigurationExtentionDto InsertAsync(FreightConfigurationExtentionRequestDto dto)
        {
            //1 检查车型是否存在
            CheckVehicleType(dto.VehicleTypeId);
            //2 检查零担运费配置是否已存在
            CheckLti(dto);
            //3 新增运费配置
            FreightConfigurationExtentionEntity entity = dto.As<FreightConfigurationExtentionEntity>();
            entity.CreateTime = DateTime.Now;
            entity.UpdateTime = DateTime.Now;
            var result = freightConfigurationExtentionData.Add(entity).GetAwaiter().GetResult().As<FreightConfigurationExtentionDto>();
            this.redisService.DeleteMultipleKey(key, false);
            return result;
        }

        public FreightConfigurationExtentionDto UpdateAsync(bool isSystemAccount, int freightConfigurationExtentionId, FreightConfigurationExtentionPutDto dto)
        {
            //1 检查零担运费配置是否已存在
            //CheckLti(dto);
            var freightConfig = freightConfigurationExtentionData.GetById(freightConfigurationExtentionId).Result;
            if (freightConfig == null)
            {
                throw new ArgumentException("零担运费配置信息不存在");
            }
            freightConfig.StartPrice = dto.StartPrice;
            freightConfig.FirstWeight = dto.FirstWeight;
            freightConfig.MaxWeight = dto.MaxWeight;
            freightConfig.EveryWeightPrice = dto.EveryWeightPrice;
            freightConfig.SameCityMaxMileage = dto.SameCityMaxMileage;
            freightConfig.SameCityRatio = dto.SameCityRatio;
            freightConfig.SameProvinceMileage = dto.SameProvinceMileage;
            freightConfig.SameProvinceRatio = dto.SameProvinceRatio;
            freightConfig.MileagePrice = dto.MileagePrice;
            freightConfig.UpdateTime = DateTime.Now;
            freightConfigurationExtentionData.Update(freightConfig).GetAwaiter().GetResult();
            this.redisService.DeleteMultipleKey(key, false);
            return freightConfig.As<FreightConfigurationExtentionDto>();
        }

        public void DeleteAsync(int freightConfigurationExtentionId)
        {
            freightConfigurationExtentionData.Delete(freightConfigurationExtentionId).GetAwaiter().GetResult();
            this.redisService.DeleteMultipleKey(key, false);
        }

        public FreightConfigurationExtentionDto GetById(int freightConfigurationExtentionId)
        {
            string cacheKey = this.redisService.GetKey(key, freightConfigurationExtentionId);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = freightConfigurationExtentionData.GetById(freightConfigurationExtentionId).Result;
                return data.As<FreightConfigurationExtentionDto>();
            }, TimeSpan.FromDays(30));
            return result;
        }

        public PageableList<FreightConfigurationExtentionDto> GetAll(AdminDto admin, FreightConfigExtentionListRequestDto dto)
        {
            string cacheKey = this.redisService.GetKey(key, dto.As<FreightConfigurationExtentionViewEntity>());
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var (list, count) = freightConfigurationExtentionData.GetAll(admin.AgentRecord?.AgentRecordId, dto.As<FreightConfigurationExtentionViewEntity>()).Result;
                return new PageableList<FreightConfigurationExtentionDto>()
                {
                    Count = count,
                    Items = list.As<IEnumerable<FreightConfigurationExtentionDto>>()
                };
            }, TimeSpan.FromDays(30));
            return result;
        }

        #endregion 公共方法

        #region 私有方法

        /// <summary>
        /// 检查零担运费配置是否已存在
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        private void CheckLti(FreightConfigurationExtentionRequestDto dto)
        {
            var ltiInfo = freightConfigurationExtentionData.CheckFreightConfigurationExtentionExists(dto.ProvinceCode, dto.CityCode, dto.CountyCode, dto.FirstWeight, dto.MaxWeight, dto.StartPrice, dto.EveryWeightPrice, dto.SourceType, dto.FreightType, dto.VehicleTypeId).Result;
            if (ltiInfo)
                throw new ArgumentException("零担运费配置已存在");
        }

        public bool InitRepair()
        {
            var result = this.freightConfigurationExtentionData.GetCountyCodeList().Result;
            var county = this.countyData.GetList().Result;
            if (result.Any() && county.Any())
            {
                if (result.Count() != county.Count())
                {
                    var tempList = county.Select(p => p.CountyCode).Except(result).ToList();
                    foreach (var item in tempList)
                    {
                        this.freightConfigurationExtentionData.InsertReparir(item, result.FirstOrDefault()).GetAwaiter().GetResult();
                    }
                    this.redisService.DeleteMultipleKey(key, false);
                }
            }
            var vehicleTypeList = this.vehicleTypeData.GetList().Result;
            var vehicleTypeIdList = this.freightConfigurationExtentionData.GetVehicleTypeIdList().Result;
            if (vehicleTypeIdList != null && vehicleTypeIdList.Any())
            {
                foreach (var item in vehicleTypeList)
                {
                    if (!vehicleTypeIdList.Any(p => p == item.VehicleTypeId))
                    {
                        this.freightConfigurationExtentionData.InsertReparir(vehicleTypeIdList.FirstOrDefault(), item.VehicleTypeId).GetAwaiter().GetResult();
                    }
                }
                this.redisService.DeleteMultipleKey(key, false);
            }
            return true;
        }

        #endregion 私有方法

        /// <summary>
        /// 检查车辆类型是否存在
        /// </summary>
        /// <param name="vehicleTypeId">车辆类型id</param>
        /// <returns></returns>
        private VehicleTypeDto CheckVehicleType(int vehicleTypeId)
        {
            string cacheKey = this.redisService.GetKey(vehicleTypeKey, vehicleTypeId);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var vehicleTypeInfo = vehicleTypeService.GetById(vehicleTypeId);
                if (vehicleTypeInfo == null)
                    throw new ArgumentException("车辆类型不存在");
                if (!vehicleTypeInfo.Enabled)
                    throw new ArgumentException("车型已被禁用，无法执行新增运费配置操作");
                return vehicleTypeInfo;
            }, TimeSpan.FromDays(1));
            return result;
        }

        public FreightConfigurationExtentionDto Get(int? vehicleTypeId, string ProvinceCode, string CityCode, string CountyCode, OrderSourceType? sourceType, FreightType? freightType)
        {
            string cacheKey = this.redisService.GetKey(key, vehicleTypeId, ProvinceCode, CityCode, CountyCode, sourceType, freightType);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                return freightConfigurationExtentionData.GetFreight(vehicleTypeId, ProvinceCode, CityCode, CountyCode, sourceType, freightType).GetAwaiter().GetResult().As<FreightConfigurationExtentionDto>();
            }, TimeSpan.FromDays(30));
            return result;
        }

        public FreightConfigurationExtentionDto Get(string countyCode,decimal maxWeight,OrderSourceType orderSourceType,FreightType? freightType)
        {
            string cacheKey = this.redisService.GetKey(key, countyCode);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                return freightConfigurationExtentionData.Get(countyCode, maxWeight, orderSourceType, freightType).GetAwaiter().GetResult().As<FreightConfigurationExtentionDto>();
            }, TimeSpan.FromDays(30));
            return result;
        }
    }
}